/*
	This file is part of Warzone 2100.
	Copyright (C) 1999-2004  Eidos Interactive
	Copyright (C) 2005-2007  Warzone Resurrection Project

	Warzone 2100 is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	Warzone 2100 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Warzone 2100; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
 * @file advvis.c
 * 
 * Makes smooth transitions for terrain visibility.
 */

#include "lib/framework/frame.h"
#include "lib/gamelib/gtime.h"

#include "advvis.h"
#include "display3d.h"
#include "hci.h"
#include "map.h"

// ------------------------------------------------------------------------------------
#define FADE_IN_TIME	(GAME_TICKS_PER_SEC/10)
#define	START_DIVIDE	(8)

static UDWORD avConsidered;
static UDWORD avCalculated;
static UDWORD avIgnored;
static BOOL bRevealActive = false;


// ------------------------------------------------------------------------------------
void	avSetStatus(BOOL var)
{
	debug(LOG_FOG, "avSetStatus: Setting fog of war %s", var ? "ON" : "OFF");
	bRevealActive = var;
}

void	avInformOfChange(SDWORD x, SDWORD y)
{
MAPTILE	*psTile;
SDWORD	lowerX,upperX,lowerY,upperY;

	psTile= mapTile(x,y);
	if(psTile->level < 0)
	{
		lowerX = player.p.x/TILE_UNITS;
		upperX = lowerX + visibleTiles.x;
		lowerY = player.p.z/TILE_UNITS;
		upperY = lowerY + visibleTiles.y;
		if(lowerX<0) lowerX = 0;
		if(lowerY<0) lowerY = 0;
		if(x>lowerX && x<upperX && y>lowerY && y<upperY)
		{
			/* tile is on grid - so initiate fade up */
			psTile->level = 0;
		}
		else
		{
			/* tile is off the grid, so force to maximum and finish */
			psTile->level = psTile->illumination;
			psTile->bMaxed = true;
		}
	}
	else
	{
		/* Already know about this one - so exit */
		return;
	}
}


// ------------------------------------------------------------------------------------
static void processAVTile(UDWORD x, UDWORD y)
{
	MAPTILE *psTile;
	float newLevel;

	psTile = mapTile(x, y);
	if (psTile->level < 0 || psTile->bMaxed)
	{
		return;
	}

	newLevel = psTile->level + timeAdjustedIncrement(FADE_IN_TIME, true);
	if (newLevel >= psTile->illumination)
	{
		psTile->level = psTile->illumination;
		psTile->bMaxed = true;
	}
	else
	{
		psTile->level = newLevel;
	}
}


// ------------------------------------------------------------------------------------
void	avUpdateTiles( void )
{
SDWORD	startX,startY,endX,endY;
UDWORD	i,j;

	/* Clear stats */
	avConsidered = 0;
	avCalculated = 0;
	avIgnored = 0;

  	/* Only process the ones on the grid. Find top left */
	if(player.p.x>=0)
	{
		startX = player.p.x/TILE_UNITS;
	}
	else
	{
		startX = 0;
	}
	if(player.p.z >= 0)
	{
		startY = player.p.z/TILE_UNITS;
	}
	else
	{
		startY = 0;
	}

	/* Find bottom right */
	endX = startX + visibleTiles.x;
	endY = startY + visibleTiles.y;

	/* Clip, as we may be off map */
	if(startX<0) startX = 0;
	if(startY<0) startY = 0;
	if(endX>(SDWORD)(mapWidth-1))  endX = (SDWORD)(mapWidth-1);
	if(endY>(SDWORD)(mapHeight-1)) endY =(SDWORD)(mapHeight-1);

	/* Go through the grid */
	for(i=startY; i<(UDWORD)endY; i++)
	{
		for(j=startX; j<(UDWORD)endX; j++)
		{
			processAVTile(j,i);
		}
	}

	avConsidered = (visibleTiles.x * visibleTiles.y);
}


// ------------------------------------------------------------------------------------
UDWORD	avGetObjLightLevel(BASE_OBJECT *psObj,UDWORD origLevel)
{
	float div = (float)psObj->visible[selectedPlayer] / 255.f;

	unsigned int lowest = origLevel / START_DIVIDE;
	unsigned int newLevel = div * origLevel;

	if(newLevel < lowest)
	{
		newLevel = lowest;
	}

	return newLevel;
}

// ------------------------------------------------------------------------------------
void	avGetStats(UDWORD *considered, UDWORD *ignored, UDWORD *calculated)
{
	*considered = avConsidered;
	*ignored	= avIgnored;
	*calculated = avCalculated;
}

// ------------------------------------------------------------------------------------
BOOL	getRevealStatus( void )
{
	return(bRevealActive);
}

// ------------------------------------------------------------------------------------
void	setRevealStatus( BOOL val )
{
	debug(LOG_FOG, "avSetRevealStatus: Setting reveal to %s", val ? "ON" : "OFF");
	bRevealActive = val;
}

// ------------------------------------------------------------------------------------
void	preProcessVisibility( void )
{
UDWORD		i,j;
MAPTILE		*psTile;

	for(i=0; i<mapWidth;i++)
	{
		for(j=0; j<mapHeight; j++)
		{
			psTile = mapTile(i,j);
		   	if(TEST_TILE_VISIBLE(selectedPlayer,psTile))
		  	{
				psTile->bMaxed = true;
				psTile->level = psTile->illumination;
		  	}
			else
			{
			 	psTile->level = -1;
				psTile->bMaxed = false;
			}
		}
	}


}
// ------------------------------------------------------------------------------------
